using Baci.Net.ToolKit.ArcGISProGeoprocessor.Models;
using Baci.Net.ToolKit.ArcGISProGeoprocessor.Models.Attributes;
using Baci.Net.ToolKit.ArcGISProGeoprocessor.Models.Attributes.DomainAttributes;
using Baci.Net.ToolKit.ArcGISProGeoprocessor.Models.Enums;
using System.Collections.Generic;
using System.ComponentModel;

namespace Baci.ArcGIS._RasterAnalysisTools._Hydrology
{
    /// <summary>
    /// <para>Flow Direction</para>
    /// <para>Calculates the direction of flow from each cell to its downslope neighbor or neighbors using the D8, D-Infinity (DINF), or Multiple Flow Direction (MFD) method.</para>
    /// <para>使用 D8、D-无穷大 （DINF） 或多流向 （MFD） 方法计算从每个像元到其下坡相邻单元的流向。</para>
    /// </summary>    
    [DisplayName("Flow Direction")]
    public class FlowDirection : AbstractGPProcess
    {
        /// <summary>
        /// 无参构造
        /// </summary>
        public FlowDirection()
        {

        }

        /// <summary>
        /// 有参构造
        /// </summary>
        /// <param name="_inputSurfaceRaster">
        /// <para>Input Surface Raster</para>
        /// <para>The input raster representing a continuous surface.</para>
        /// <para>表示连续表面的输入栅格。</para>
        /// </param>
        /// <param name="_outputFlowDirectionName">
        /// <para>Output Flow Direction Name</para>
        /// <para><xdoc>
        ///   <para>The name of the output flow direction raster service.</para>
        ///   <para>The default name is based on the tool name and the input layer name. If the layer name already exists, you will be prompted to provide another name.</para>
        /// </xdoc></para>
        /// <para><xdoc>
        ///   <para>输出流向栅格服务的名称。</para>
        ///   <para>默认名称基于工具名称和输入图层名称。如果图层名称已存在，系统将提示您提供其他名称。</para>
        /// </xdoc></para>
        /// </param>
        public FlowDirection(object _inputSurfaceRaster, object _outputFlowDirectionName)
        {
            this._inputSurfaceRaster = _inputSurfaceRaster;
            this._outputFlowDirectionName = _outputFlowDirectionName;
        }
        public override string ToolboxName => "Raster Analysis Tools";

        public override string ToolName => "Flow Direction";

        public override string CallName => "ra.FlowDirection";

        public override List<string> AcceptEnvironments => ["cellSize", "extent", "mask", "outputCoordinateSystem", "snapRaster"];

        public override object[] ParameterInfo => [_inputSurfaceRaster, _outputFlowDirectionName, _forceFlow.GetGPValue(), _flowDirectionType.GetGPValue(), _outputDropName, _outputFlowDirectionRaster, _outputDropRaster];

        /// <summary>
        /// <para>Input Surface Raster</para>
        /// <para>The input raster representing a continuous surface.</para>
        /// <para>表示连续表面的输入栅格。</para>
        /// <para></para>
        /// </summary>
        [DisplayName("Input Surface Raster")]
        [Description("")]
        [Option(OptionTypeEnum.Must)]
        public object _inputSurfaceRaster { get; set; }


        /// <summary>
        /// <para>Output Flow Direction Name</para>
        /// <para><xdoc>
        ///   <para>The name of the output flow direction raster service.</para>
        ///   <para>The default name is based on the tool name and the input layer name. If the layer name already exists, you will be prompted to provide another name.</para>
        /// </xdoc></para>
        /// <para><xdoc>
        ///   <para>输出流向栅格服务的名称。</para>
        ///   <para>默认名称基于工具名称和输入图层名称。如果图层名称已存在，系统将提示您提供其他名称。</para>
        /// </xdoc></para>
        /// <para></para>
        /// </summary>
        [DisplayName("Output Flow Direction Name")]
        [Description("")]
        [Option(OptionTypeEnum.Must)]
        public object _outputFlowDirectionName { get; set; }


        /// <summary>
        /// <para>Force all edge cells to flow outward</para>
        /// <para><xdoc>
        ///   <para>Specifies if edge cells will always flow outward or follow normal flow rules.</para>
        ///   <bulletList>
        ///     <bullet_item>Unchecked—If the maximum drop on the inside of an edge cell is greater than zero, the flow direction will be determined as usual; otherwise, the flow direction will be toward the edge. Cells that should flow from the edge of the surface raster inward will do so. This is the default.</bullet_item><para/>
        ///     <bullet_item>Checked—All cells at the edge of the surface raster will flow outward from the surface raster.</bullet_item><para/>
        ///   </bulletList>
        /// </xdoc></para>
        /// <para><xdoc>
        ///   <para>指定边像元是始终向外流动还是遵循正常流动规则。</para>
        ///   <bulletList>
        ///     <bullet_item>未选中 （Uncted） - 如果边像元内部的最大落差大于零，则将照常确定流动方向;否则，流向将朝向边缘。应从表面栅格边缘向内流动的像元将这样做。这是默认设置。</bullet_item><para/>
        ///     <bullet_item>选中 - 表面栅格边缘的所有像元都将从表面栅格向外流动。</bullet_item><para/>
        ///   </bulletList>
        /// </xdoc></para>
        /// <para></para>
        /// </summary>
        [DisplayName("Force all edge cells to flow outward")]
        [Description("")]
        [Option(OptionTypeEnum.optional)]
        public _forceFlow_value _forceFlow { get; set; } = _forceFlow_value._false;

        public enum _forceFlow_value
        {
            /// <summary>
            /// <para>FORCE</para>
            /// <para></para>
            /// <para></para>
            /// </summary>
            [Description("FORCE")]
            [GPEnumValue("true")]
            _true,

            /// <summary>
            /// <para>NORMAL</para>
            /// <para></para>
            /// <para></para>
            /// </summary>
            [Description("NORMAL")]
            [GPEnumValue("false")]
            _false,

        }

        /// <summary>
        /// <para>Flow Direction Type</para>
        /// <para><xdoc>
        ///   <para>Specifies the type of flow method to use while computing flow directions.</para>
        ///   <bulletList>
        ///     <bullet_item>D8—Assign a flow direction based on the D8 flow method. This method assigns flow direction to the steepest downslope neighbor. This is the default.</bullet_item><para/>
        ///     <bullet_item>MFD—Assign a flow direction based on the MFD flow method. This method assigns multiple flow directions towards all downslope neighbors.</bullet_item><para/>
        ///     <bullet_item>DINF—Assign a flow direction based on the D-Infinity flow method using the steepest slope of a triangular facet.</bullet_item><para/>
        ///   </bulletList>
        /// </xdoc></para>
        /// <para><xdoc>
        ///   <para>指定计算流向时要使用的流方法的类型。</para>
        ///   <bulletList>
        ///     <bullet_item>D8 - 根据 D8 流法指定流向。此方法将流向分配给最陡峭的下坡邻居。这是默认设置。</bullet_item><para/>
        ///     <bullet_item>MFD - 根据 MFD 流方法指定流向。此方法将多个流向所有下坡邻居。</bullet_item><para/>
        ///     <bullet_item>DINF - 使用三角形面的最陡坡，根据 D-Infinity 流动方法指定流向。</bullet_item><para/>
        ///   </bulletList>
        /// </xdoc></para>
        /// <para></para>
        /// </summary>
        [DisplayName("Flow Direction Type")]
        [Description("")]
        [Option(OptionTypeEnum.optional)]
        public _flowDirectionType_value _flowDirectionType { get; set; } = _flowDirectionType_value._D8;

        public enum _flowDirectionType_value
        {
            /// <summary>
            /// <para>D8</para>
            /// <para>D8—Assign a flow direction based on the D8 flow method. This method assigns flow direction to the steepest downslope neighbor. This is the default.</para>
            /// <para>D8 - 根据 D8 流法指定流向。此方法将流向分配给最陡峭的下坡邻居。这是默认设置。</para>
            /// </summary>
            [Description("D8")]
            [GPEnumValue("D8")]
            _D8,

            /// <summary>
            /// <para>MFD</para>
            /// <para>MFD—Assign a flow direction based on the MFD flow method. This method assigns multiple flow directions towards all downslope neighbors.</para>
            /// <para>MFD - 根据 MFD 流方法指定流向。此方法将多个流向所有下坡邻居。</para>
            /// </summary>
            [Description("MFD")]
            [GPEnumValue("MFD")]
            _MFD,

            /// <summary>
            /// <para>DINF</para>
            /// <para>DINF—Assign a flow direction based on the D-Infinity flow method using the steepest slope of a triangular facet.</para>
            /// <para>DINF - 使用三角形面的最陡坡，根据 D-Infinity 流动方法指定流向。</para>
            /// </summary>
            [Description("DINF")]
            [GPEnumValue("DINF")]
            _DINF,

        }

        /// <summary>
        /// <para>Output Drop Name</para>
        /// <para><xdoc>
        ///   <para>The name of the output drop raster service.</para>
        ///   <para>The default name is based on the tool name and the input layer name. If the layer name already exists, you will be prompted to provide another name.</para>
        /// </xdoc></para>
        /// <para><xdoc>
        ///   <para>输出放置栅格服务的名称。</para>
        ///   <para>默认名称基于工具名称和输入图层名称。如果图层名称已存在，系统将提示您提供其他名称。</para>
        /// </xdoc></para>
        /// <para></para>
        /// </summary>
        [DisplayName("Output Drop Name")]
        [Description("")]
        [Option(OptionTypeEnum.optional)]
        public object _outputDropName { get; set; } = null;


        /// <summary>
        /// <para>Output Flow Direction Raster</para>
        /// <para></para>
        /// <para></para>
        /// <para></para>
        /// </summary>
        [DisplayName("Output Flow Direction Raster")]
        [Description("")]
        [Option(OptionTypeEnum.derived)]
        public object _outputFlowDirectionRaster { get; set; }


        /// <summary>
        /// <para>Output Drop Raster</para>
        /// <para></para>
        /// <para></para>
        /// <para></para>
        /// </summary>
        [DisplayName("Output Drop Raster")]
        [Description("")]
        [Option(OptionTypeEnum.derived)]
        public object _outputDropRaster { get; set; }


        public FlowDirection SetEnv(object cellSize = null, object extent = null, object mask = null, object outputCoordinateSystem = null, object snapRaster = null)
        {
            base.SetEnv(cellSize: cellSize, extent: extent, mask: mask, outputCoordinateSystem: outputCoordinateSystem, snapRaster: snapRaster);
            return this;
        }

    }

}